package com.slipper.system.employee.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.slipper.exception.CommonException;
import com.slipper.system.organization.bo.OrganizationBO;
import com.slipper.system.organization.dao.OrganizationDao;
import com.slipper.system.role.bo.RoleBO;
import com.slipper.system.role.dao.RoleDao;
import com.slipper.core.transaction.ReadTransactional;
import com.slipper.core.transaction.WriteTransactional;
import com.slipper.util.MD5;
import com.slipper.util.Tool;
import com.slipper.system.employee.bo.EmployeeBO;
import com.slipper.system.employee.dao.EmployeeDao;
import com.slipper.util.UUID;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;

import java.util.*;
import java.util.stream.Collectors;

@Service
@ReadTransactional
public class EmployeeService {
    @Resource
    private EmployeeDao employeeDao;
    @Resource
    private RoleDao roleDao;
    @Resource
    private OrganizationDao organizationDao;

    public EmployeeBO queryBy(String employeeId) {
        return employeeDao.queryBy(employeeId);
    }

    public EmployeeBO queryBy(EmployeeBO bo) {
        EmployeeBO employee = employeeDao.queryBy(bo.getId());
        employee.setRoleIds(roleDao.queryByEmployeeId(bo.getId())
                .stream().map(RoleBO::getId).collect(Collectors.joining(",")));
        employee.setOrganizationIds(organizationDao.queryByEmployeeId(bo.getId())
                .stream().map(OrganizationBO::getId).toList().toArray(new String[0]));
        return employee;
    }

    public List<EmployeeBO> queryList(EmployeeBO bo) {
        return employeeDao.queryList(bo);
    }

    public List<EmployeeBO> queryListWithOrg(EmployeeBO bo) {
        return employeeDao.queryListWithOrg(bo);
    }

    public PageInfo<EmployeeBO> queryPage(EmployeeBO bo) {
        PageHelper.startPage(bo.getPageNumber(), bo.getPageSize());
        PageInfo<EmployeeBO> pageInfo = new PageInfo<>(employeeDao.queryList(bo));
        if (!pageInfo.getList().isEmpty()) {
            String[] employeeIds = pageInfo.getList().stream().map(EmployeeBO::getId).toList().toArray(new String[0]);
            if (employeeIds.length > 0) {
                Map<String, String> dataMap = roleDao.queryByEmployeeIds(employeeIds)
                        .stream()
                        .collect(Collectors.groupingBy(
                                RoleBO::getEmployeeId,
                                Collectors.reducing(
                                        "",
                                        RoleBO::getId,
                                        (s1, s2) -> Tool.isBlank(s1) ? s2 : s1.concat(",").concat(s2)))
                        );
                pageInfo.getList().forEach(employee -> employee.setRoleIds(dataMap.get(employee.getId())));
            }
        }
        return pageInfo;
    }

    @WriteTransactional
    public int save(EmployeeBO bo) {
        if (!Tool.isBlank(bo.getUsername()) && this.employeeDao.queryUseBy(bo) > 0) {
            throw new CommonException("登录账号【" + bo.getUsername()  + "】已经被使用！");
        }

        int result;
        if (Tool.isNotBlank(bo.getPassword())) {
            bo.setPassword(MD5.encodePwd(bo.getPassword()));
        }
        if (Tool.isNotBlank(bo.getId())) {
            bo.setUpdateTime(System.currentTimeMillis());
            result = employeeDao.update(bo);
        } else {
            bo.setId(UUID.getUUID());
            bo.setUpdateTime(System.currentTimeMillis());
            bo.setCreateTime(System.currentTimeMillis());
            result = employeeDao.insert(bo);
        }

        result += this.employeeDao.deleteEmployeeRole(bo.getId());
        if (bo.getRoleIds() != null) {
            for (String roleId : bo.getRoleIds().split(",")) {
                result += this.employeeDao.saveEmployeeRole(UUID.getUUID(), bo.getId(), roleId);
            }
        }

        result += this.employeeDao.deleteEmployeeOrganization(bo.getId());
        Set<String> orgIdSet = new HashSet<>();
        if (bo.getOrganizationId() != null) {
            orgIdSet.add(bo.getOrganizationId());
        }
        if (bo.getOrganizationIds() != null) {
            Collections.addAll(orgIdSet, bo.getOrganizationIds());
        }
        orgIdSet.forEach(orgId -> this.employeeDao.saveEmployeeOrganization(UUID.getUUID(), bo.getId(), orgId));

        return result;
    }

    @WriteTransactional
    public Integer updatePassword(EmployeeBO bo) {
        bo.setPassword(MD5.encodePwd(bo.getPassword()));
        return this.employeeDao.updatePassword(bo);
    }

    @WriteTransactional
    public int delete(EmployeeBO bo) {
        String[] ids = null;
        if (Tool.isNotBlank(bo.getId())) {
            ids = new String[] { bo.getId() };
        }
        if (bo.getIds() != null && bo.getIds().length > 0) {
            ids = bo.getIds();
        }
        if (ids != null) {
            for (String id : ids) {
                this.employeeDao.deleteEmployeeRole(id);
                this.employeeDao.deleteEmployeeOrganization(id);
            }
        }

        return employeeDao.delete(bo);
    }

    public EmployeeBO queryByLogin(EmployeeBO bo) {
        List<EmployeeBO> employeeList = employeeDao.queryByLogin(bo);
        return employeeList.isEmpty() ? null : employeeList.getFirst();
    }

    @WriteTransactional
    public Integer saveUserRole(EmployeeBO bo) {
        int result = this.employeeDao.deleteEmployeeRole(bo.getId());

        if (bo.getRoleIds() != null) {
            for (String roleId : bo.getRoleIds().split(",")) {
                result += this.employeeDao.saveEmployeeRole(UUID.getUUID(), bo.getId(), roleId);
            }
        }

        return result;
    }

    public List<EmployeeBO> queryByIds(EmployeeBO bo) {
        return this.employeeDao.queryByIds(bo);
    }

    @WriteTransactional
    public void updateOrganization(EmployeeBO employee) {
        this.employeeDao.updateOrganization(employee);
    }

    @WriteTransactional
    public int updateTheme(EmployeeBO employee) {
        return this.employeeDao.updateTheme(employee);
    }

    public Map<String, Object> queryMapData(String id) {
        return employeeDao.queryMapData(id);
    }
}
